package com.wenlin.myproduction.ui;


import android.content.Intent;
import android.os.Bundle;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.wenlin.myproduction.R;
import com.wenlin.myproduction.base.BaseActivity;
import com.wenlin.myproduction.base.BaseSwipeActivity;
import com.wenlin.myproduction.bean.RosterSelectWithChangeBean;
import com.wenlin.myproduction.bean.ScheduleContentBean;
import com.wenlin.myproduction.bean.ScheduleContentClickBean;
import com.wenlin.myproduction.bean.ScheduleLeftBean;
import com.wenlin.myproduction.bean.ScheduleRecordBean;
import com.wenlin.myproduction.bean.ScheduleTopBean;
import com.wenlin.myproduction.bean.ScheduleTopTotalBean;
import com.wenlin.myproduction.binder.ScheduleContentBinder;
import com.wenlin.myproduction.binder.ScheduleLeftBinder;
import com.wenlin.myproduction.binder.ScheduleTopBinder;
import com.wenlin.myproduction.binder.ScheduleTopTotalBinder;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.MyGridLayoutManager;
import com.wenlin.myproduction.util.RosterUtil;
import com.wenlin.myproduction.util.ScheduleUtil;
import com.wenlin.myproduction.util.TimeUtil;
import com.wenlin.myproduction.util.TypeData;
import com.wenlin.myproduction.util.TypeDataNames;
import com.wenlin.myproduction.util.UI;
import com.wenlin.myproduction.util.ValCommon;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import me.drakeet.multitype.Items;
import me.drakeet.multitype.MultiTypeAdapter;

/**
 * @author 文琳
 * @Email 377979485@qq.com
 * @desc 排班管理。双向滑动列表部分分成四个部分，分别是姓名标签、标题栏列表、护士名称列表、排班列表。姓名标签用TextView，
 * 标题栏列表、护士名称列表、排班列表都是一个RecyclerView。然后将标题栏列表和排班列表的两个RecyclerView用HorizonScrollView
 * 包起来。再添加滑动监听，让护士名称列表随着排班列表纵向同时滑动，让排班列表随着护士名称列表纵向同时滑动。
 * 横向滑动直接交给HorizonScrollView处理。不做额外设置。
 * @time 2023-02-02 星期四 15:35
 */
public class ScheduleManageActivity extends BaseSwipeActivity {
    @BindView(R.id.rv_top)
    RecyclerView rvTop;
    @BindView(R.id.rv_left)
    RecyclerView rvLeft;
    @BindView(R.id.rv_content)
    RecyclerView rvContent;
    @BindView(R.id.hsv)
    HorizontalScrollView hsv;

    private Items itemsTop = new Items();
    private MultiTypeAdapter adapterTop;
    private Items itemsLeft = new Items();
    private MultiTypeAdapter adapterLeft;
    private Items itemsContent = new Items();
    private MultiTypeAdapter adapterContent;
    private ScheduleContentClickBean clickBean;//点击了自定义控件中的某个子条目，返回该行数据和点击位置
    private RosterSelectDialog rosterSelectDialog;
    private ScheduleRecordBean bean;
    //arrOri放的是数据接口传来的字符串，带p标签。
    //arrEdit先根据arrOri对应的位置有没有值，默认显示“”或者“locked”这两种类型。然后根据用户的修改动作进行覆盖填入，比如将“2_0”覆盖填入。
    //arrName就是提交时的护士的参数名，带行和列两个参数，行就是护士id，列就是从左到右，从0开始递增的自然数表示位置。
    private String[][] arrOri, arrEdit, arrName;
    private int positionToday;//今天的日期在列表中所处的位置，找不到的话就置为0。用于自动滑动到当天所在的列表位置。

    @Override
    public int getContentView() {
        return R.layout.activity_schedule_manager;
    }

    public static void start(BaseActivity activity) {
        Intent intent = new Intent(activity, ScheduleManageActivity.class);
        activity.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle(ValCommon.SCHEDULE_MANAGE);
        adapterTop = new MultiTypeAdapter(itemsTop);
        adapterTop.register(ScheduleTopBean.class, new ScheduleTopBinder());
        adapterTop.register(ScheduleTopTotalBean.class, new ScheduleTopTotalBinder());
        LinearLayoutManager topManager = new LinearLayoutManager(this);
        topManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        rvTop.setLayoutManager(topManager);
        rvTop.setHasFixedSize(true);
        rvTop.setAdapter(adapterTop);
        //left
        adapterLeft = new MultiTypeAdapter(itemsLeft);
        adapterLeft.register(ScheduleLeftBean.class, new ScheduleLeftBinder());
        rvLeft.setLayoutManager(new MyGridLayoutManager(this, 1));
        rvLeft.setHasFixedSize(true);
        rvLeft.setAdapter(adapterLeft);
        final RecyclerView.OnScrollListener leftListener = new SelfRemovingOnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                    rvContent.scrollBy(dx, dy);
                }
            }
        };
        rvLeft.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            private int mLastY;

            @Override
            public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
                if (rvContent.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) {
                    return true;
                }
                boolean ret = rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
                if (!ret) {
                    onTouchEvent(rv, e);
                }
                return false;
            }

            @Override
            public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
                final int action;
                if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && rvContent.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                    mLastY = rv.getScrollY();
                    rv.removeOnScrollListener(leftListener);
                    rv.addOnScrollListener(leftListener);
                } else {
                    if (action == MotionEvent.ACTION_UP && rv.getScrollY() == mLastY) {
                        rv.removeOnScrollListener(leftListener);
                    }
                }
            }

            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

            }
        });
        //content
        adapterContent = new MultiTypeAdapter(itemsContent);
        adapterContent.register(ScheduleContentBean.class, new ScheduleContentBinder());
        rvContent.setLayoutManager(new GridLayoutManager(this, 1));
        rvContent.setHasFixedSize(true);
        rvContent.setAdapter(adapterContent);
        final RecyclerView.OnScrollListener contentListener = new SelfRemovingOnScrollListener() {
            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (recyclerView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE) {
                    rvLeft.scrollBy(dx, dy);
                }
            }
        };
        rvContent.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            private int mLastY;

            @Override
            public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
                if (rvLeft.getScrollState() == RecyclerView.SCROLL_STATE_SETTLING) {
                    return true;
                }
                boolean ret = rv.getScrollState() != RecyclerView.SCROLL_STATE_IDLE;
                if (!ret) {
                    onTouchEvent(rv, e);
                }
                return false;
            }

            @Override
            public void onTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
                final int action;
                if ((action = e.getAction()) == MotionEvent.ACTION_DOWN && rvLeft.getScrollState() == RecyclerView.SCROLL_STATE_IDLE) {
                    mLastY = rv.getScrollY();
                    rv.removeOnScrollListener(contentListener);
                    rv.addOnScrollListener(contentListener);
                } else {
                    if (action == MotionEvent.ACTION_UP && rv.getScrollY() == mLastY) {
                        rv.removeOnScrollListener(contentListener);
                    }
                }
            }

            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

            }
        });
        //加载数据
        bean = ScheduleUtil.getScheduleRecordBean();
        if (Checker.isNull(bean)) return;
        int row = bean.getLists().size();//这里的行，就是护士的个数
        int column = 7;//这里的列，就是标题的日期的个数
        arrOri = new String[row][column];
        arrName = new String[row][column];
        arrEdit = new String[row][column];
        List<ScheduleRecordBean.ListsDTO> listsDTO = bean.getLists();
        if (Checker.hasList(listsDTO)) {
            for (int i = 0; i < listsDTO.size(); i++) {
                ScheduleRecordBean.ListsDTO rowBean = listsDTO.get(i);
                List<String> columnBean = rowBean.getSchedule_arr();
                if (Checker.hasList(columnBean)) {
                    for (int j = 0; j < columnBean.size(); j++) {
                        String content = columnBean.get(j);
                        arrOri[i][j] = content;//从数据接口中获取到的排班内容，可能为“”或者带p标签的字符串“”
                        arrEdit[i][j] = Checker.hasWord(content) ? ValCommon.LOCKED : "";//这里如果原来的排班有值则arrEdit直接填入“locked”。如果后面有改动，会覆盖掉。设置班次后值为“2_1”，第一个数字为班次编号，第二个数字为是否调班。
                        arrName[i][j] = "nurse_" + rowBean.getId() + "_" + j;//提交时用到的护士的参数名，比如“nurse_127_1”作为参数名表示护士id为127的第2天的排班。参数为arrEdit对应位置的值，比如“2_1”。
                    }
                }
            }
        }
        //top
        List<ScheduleTopBean> listTop = new ArrayList<>();
        List<String> listDateStrOri = RosterUtil.getCurrentWeekList();
        String dateToday = TimeUtil.getTodayMonthDay();
        for (int i = 0; i < listDateStrOri.size(); i++) {
            String dateStrOri = listDateStrOri.get(i);
            ScheduleTopBean stb = ScheduleUtil.getScheduleTopBeanFromStr(dateStrOri);
            if (dateToday.equals(stb.getDate())) {
                positionToday = i;
            }
            listTop.add(stb);
        }
        if (Checker.hasList(itemsTop)) {
            itemsTop.clear();
            adapterTop.notifyDataSetChanged();
        }
        itemsTop.addAll(listTop);
        adapterTop.notifyDataSetChanged();
        //增加两个额外的列——夜班数和上班时长
        itemsTop.add(new ScheduleTopTotalBean("夜班数"));
        adapterTop.notifyDataSetChanged();
        itemsTop.add(new ScheduleTopTotalBean("上班时长\n(小时)"));
        adapterTop.notifyDataSetChanged();
        //left and content
        List<ScheduleRecordBean.ListsDTO> listsDTOS = bean.getLists();
        List<ScheduleLeftBean> listLeft = new ArrayList<>();
        List<ScheduleContentBean> listContent = new ArrayList<>();
        if (Checker.hasList(listsDTOS)) {
            for (int i = 0; i < listsDTOS.size(); i++) {
                listLeft.add(new ScheduleLeftBean(listsDTOS.get(i)));
                ScheduleContentBean contentBean = new ScheduleContentBean(listsDTOS.get(i));
                contentBean.setEdit(true);//设置Edit的值为真，表示已经开启编辑模式
                listContent.add(contentBean);
            }
        }
        if (Checker.hasList(itemsLeft)) {
            itemsLeft.clear();
            adapterLeft.notifyDataSetChanged();
        }
        itemsLeft.addAll(listLeft);
        adapterLeft.notifyDataSetChanged();
        if (Checker.hasList(itemsContent)) {
            itemsContent.clear();
            adapterContent.notifyDataSetChanged();
        }
        itemsContent.addAll(listContent);
        adapterContent.notifyDataSetChanged();
        if (Checker.notNull(hsv)) hsv.postDelayed(() -> {
            //自动滑动到当天
            hsv.smoothScrollTo((int) (positionToday * UI.getPx(R.dimen.wpx168)), 0);
        }, 500);
    }

    @Override
    protected void onDestroy() {
        UI.dismiss(rosterSelectDialog);
        super.onDestroy();
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void threadHandle(TypeData typeData) {
        String name = typeData.getName();
        if (name.equals(TypeDataNames.clickScheduleContentViewOnPosition)) {//删除排班记录，如果是加号则去弹窗添加排班记录
            ScheduleContentClickBean bean = (ScheduleContentClickBean) typeData.getData();
            if (Checker.isNull(bean)) return;
            clickBean = bean;
            if (Checker.notNull(bean.getListsDTO())) {
                //先删除内容，让控件显示蓝色加号
                if (Checker.hasList(itemsContent)) {
                    for (int i = 0; i < itemsContent.size(); i++) {
                        Object o = itemsContent.get(i);
                        if (o instanceof ScheduleContentBean) {
                            ScheduleContentBean scheduleContentBean = (ScheduleContentBean) o;
                            if (Checker.notNull(scheduleContentBean.getListsDTO())) {
                                ScheduleRecordBean.ListsDTO listsDTO = scheduleContentBean.getListsDTO();
                                if (listsDTO.getId().equals(clickBean.getListsDTO().getId())) {
                                    //找到点击位置的数据了，如果有内容，则将其内容置空，并刷新列表。直接结束，不会显示选择班次弹窗
                                    List<String> listSchedule = listsDTO.getSchedule_arr();
                                    if (Checker.hasList(listSchedule) && listSchedule.size() > clickBean.getPos()) {
                                        if (Checker.hasWord(listSchedule.get(clickBean.getPos()))) {//如果有内容，则将其内容置空，并刷新列表
                                            listSchedule.set(clickBean.getPos(), "");//置空
                                            List<Integer> listNight = listsDTO.getIs_night_arr();
                                            if (Checker.hasList(listNight) && listNight.size() > clickBean.getPos()) {
                                                listNight.set(clickBean.getPos(), 0);//置空
                                            }
                                            List<String> listDuration = listsDTO.getDrt_arr();
                                            if (Checker.hasList(listDuration) && listDuration.size() > clickBean.getPos()) {
                                                listDuration.set(clickBean.getPos(), "");//置空，这里可以直接置空，自定义控件ScheduleContentView中会检查是否是数字。是数字才会去解析并计算总时长。
                                            }
                                            adapterContent.notifyDataSetChanged();
                                            arrEdit[i][clickBean.getPos()] = "";//编辑后的数组对应位置的参数置空
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            rosterSelectDialog = new RosterSelectDialog().getDialog(this).show(this);//显示班次选择弹窗
        }
        if (name.equals(TypeDataNames.setScheduleRosterSelectBean)) {//添加排班记录
            //从选择班次弹窗中返回数据，直接更新到列表的控件中
            RosterSelectWithChangeBean bean = (RosterSelectWithChangeBean) typeData.getData();
            if (Checker.isNull(bean)) return;
            if (Checker.hasList(itemsContent)) {
                for (int i = 0; i < itemsContent.size(); i++) {
                    Object o = itemsContent.get(i);
                    if (o instanceof ScheduleContentBean) {
                        ScheduleContentBean scheduleContentBean = (ScheduleContentBean) o;
                        if (Checker.notNull(scheduleContentBean.getListsDTO())) {
                            ScheduleRecordBean.ListsDTO listsDTO = scheduleContentBean.getListsDTO();
                            if (listsDTO.getId().equals(clickBean.getListsDTO().getId())) {
                                List<String> listSchedule = listsDTO.getSchedule_arr();
                                if (Checker.hasList(listSchedule) && listSchedule.size() > clickBean.getPos()) {
                                    String contentOri = arrOri[i][clickBean.getPos()];
                                    String contentEdit = ScheduleUtil.getFormatScheduleWithRosterSelectBean(bean);
                                    listSchedule.set(clickBean.getPos(), contentEdit);
                                    String result;
                                    //改之前空+改之后空=空；改之前空+改之后非空=改之后非空；改之前非空+改之后空=改之后空；改之前非空+改之后非空=>二者相同返回locked，否则返回班次id_是否调班
                                    //''+''='';''+'夜班'='2_0';'夜班'+''='';'夜班'+'夜班'='locked';'夜班'+'白班'='1_0'
                                    if (Checker.hasWord(contentEdit)) {//改后有值
                                        if (contentEdit.equals(contentOri)) {//二者相同
                                            result = ValCommon.LOCKED;
                                        } else {//二者不一样，则写入班次id_是否调班
                                            result = bean.getBean().getId() + "_" + (bean.isChange() ? 1 : 0);//0表示非调班，1表示调班。YApi原文：“班次id_是否调班(0未勾选1勾选)”
                                        }
                                    } else {//改后无值
                                        //若改前无值，则无需变动；若改前有值，则变相删除值
                                        result = "";
                                    }
                                    arrEdit[i][clickBean.getPos()] = result;
                                }
                                List<Integer> listNight = listsDTO.getIs_night_arr();
                                if (Checker.hasList(listNight) && listNight.size() > clickBean.getPos()) {
                                    listNight.set(clickBean.getPos(), ScheduleUtil.getFormatIsNight(bean));
                                }
                                List<String> listDuration = listsDTO.getDrt_arr();
                                if (Checker.hasList(listDuration) && listDuration.size() > clickBean.getPos()) {
                                    listDuration.set(clickBean.getPos(), ScheduleUtil.getFormatDuration(bean));
                                }
                                adapterContent.notifyDataSetChanged();
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    private static class SelfRemovingOnScrollListener extends RecyclerView.OnScrollListener {
        @Override
        public final void onScrollStateChanged(@NonNull final RecyclerView recyclerView, final int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                recyclerView.removeOnScrollListener(this);
            }
        }
    }
}
